package lol.clann.minecraft.springboot.plugin.bukkit.command;

import com.ruoshui.utils.java.map.MapUtils;
import lol.clann.minecraft.springboot.api.bukkit.rawmessage.RawMessage;
import lol.clann.minecraft.springboot.api.context.SpringContext;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandException;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import java.util.*;

/**
 *
 * @author pyz
 * @date 2019/5/6 7:51 PM
 */
@Getter
public class CommandDispatcher {
    private Map<String, CommandDispatcher> dispatcherMap = new LinkedHashMap<>();
    private CommandExecutor executor;
    private String command;
    @Getter
    private boolean root;

    public static CommandDispatcher from(String command, List<CommandExecutor> executors) {
        CommandDispatcher dispatcher = SpringContext.createBean(CommandDispatcher.class);
        dispatcher.root = true;
        dispatcher.command = command;
        for (CommandExecutor executor : executors) {
            dispatcher.addExecutor(executor);
        }
        return dispatcher;
    }

    private void addExecutor(CommandExecutor executor) {
        String[] mappings = executor.getMapping().split(" ");
        CommandDispatcher now = this;
        for (String mapping : mappings) {
            now = MapUtils.getOrCreate(now.dispatcherMap, mapping, () -> {
                CommandDispatcher dispatcher = new CommandDispatcher();
                dispatcher.command = mapping;
                return dispatcher;
            });
        }
        now.executor = executor;
    }

    public boolean dispatch(CommandSender commandSender, CommandContext commandContext, int index) {
        if (root) {
//          空的根指令,默认是帮助
            if (commandContext.getArgs().length == 0 && commandContext.getFalgMap().isEmpty()) {
                commandContext.getFalgMap().put("help", "");
                commandContext.getFalgMap().put("page", "0");
            }
        }
        if (root && commandContext.getFalgMap().containsKey("help")) {
            help(commandSender, commandContext);
            return true;
        }
        if (index >= commandContext.getArgs().length) {
            return execute(commandSender, commandContext);
        }
        String subCommand = commandContext.getArgs()[index];
        CommandDispatcher dispatcher = dispatcherMap.get(subCommand.toLowerCase());
        if (dispatcher != null) {
            return dispatcher.dispatch(commandSender, commandContext, index + 1);
        } else {
            return execute(commandSender, commandContext);
        }
    }

    private boolean execute(CommandSender commandSender, CommandContext commandContext) {
        if (executor == null) {
            if (dispatcherMap.isEmpty()) {
                throw new CommandException("无效指令");
            }
            int count = help(commandSender, commandContext);
            if (count == 0) {
                throw new CommandException("无效指令");
            }
            return false;
        }
        return executor.execute(commandSender, commandContext);
    }

    public void forceHelp(CommandSender commandSender) {
        if (executor != null) {
            executor.forceHelp(commandSender);
        }
        for (CommandDispatcher commandDispatcher : dispatcherMap.values()) {
            commandDispatcher.forceHelp(commandSender);
        }
    }

    private int help(CommandSender commandSender, CommandContext commandContext) {
        int count = 0;
        if (!root) {
            if (executor != null) {
                count = executor.help(commandSender);
            }
            for (CommandDispatcher commandDispatcher : dispatcherMap.values()) {
                count += commandDispatcher.help(commandSender, commandContext);
            }
        } else {
            List<RawMessage> helps = new ArrayList<>();
            if (executor != null) {
                count = executor.help(commandSender, helps);
            }
            for (CommandDispatcher commandDispatcher : dispatcherMap.values()) {
                count += commandDispatcher.help(commandSender, helps);
            }
            if (helps.size() == 0) {
                return 0;
            }
//            排序
            Collections.sort(helps);
            String pageStr = commandContext.getFalgMap().get("page");
            int page = 0;
            try {
                page = Integer.valueOf(pageStr);
                page = Math.max(0, page);
            } catch (NullPointerException | NumberFormatException e) {
                // ignore
            }
            int fromIndex = page * 10;
            int toIndex = fromIndex + 10;
            if (fromIndex >= helps.size()) {
                fromIndex = Math.max(0, helps.size() - 10);
            }
            if (toIndex >= helps.size()) {
                toIndex = helps.size();
            }
            int helpCount = helps.size();
            helps = helps.subList(fromIndex, toIndex);
            for (RawMessage help : helps) {
                help.send(commandSender);
            }
            if (root) {
//                只有根帮助,才显示分页信息
                RawMessage pager = RawMessage.createRawMessage();
                if (fromIndex > 0) {
                    pager.then(ChatColor.YELLOW + "上一页").runCommand("/" + getCommand() + " --help --page=" + (page - 1));
                }
                pager.then(ChatColor.GREEN + "=======================");
                if (toIndex < helpCount) {
                    pager.then(ChatColor.YELLOW + "下一页").runCommand("/" + getCommand() + " --help --page=" + (page + 1));
                }
                pager.send(commandSender);
            }
            count = helps.size();
        }
        return count;
    }

    private int help(CommandSender commandSender, List<RawMessage> helps) {
        int count = 0;
        if (executor != null) {
            count = executor.help(commandSender, helps);
        }
        for (CommandDispatcher commandDispatcher : dispatcherMap.values()) {
            count += commandDispatcher.help(commandSender, helps);
        }
        return count;
    }

    public void registerSubDispatcher(String subCommand, CommandDispatcher subDispatcher) {
        dispatcherMap.put(subCommand, subDispatcher);
    }

    public List<String> tabComplete(CommandSender sender, String alias, String[] args) {
        return tabComplete(sender, alias, args, 0);
    }

    public List<String> tabComplete(CommandSender sender, String alias, String[] args, int index) {
        if (index >= args.length) {
            return new ArrayList<>();
        }
        String keywords = args[index].toLowerCase();
        CommandDispatcher next = dispatcherMap.get(keywords);
        if (next == null) {
            if (executor != null && executor.getTabComplete() != null) {
//              如果有tabcomplete实现,就使用指定的实现
                return executor.getTabComplete().tabComplete(sender, alias, args);
            }
            List<String> candidates = new ArrayList<>();
            for (String candidate : dispatcherMap.keySet()) {
                if (candidate.startsWith(keywords)) {
                    candidates.add(candidate);
                }
            }
            if (candidates.isEmpty()) {
//                是空的,就从玩家列表里匹配
                for (Player player : Bukkit.getServer().getOnlinePlayers()) {
                    if (player.getName().toLowerCase().startsWith(keywords)) {
                        candidates.add(player.getName());
                    }
                }
            }
            return candidates;
        } else {
            return next.tabComplete(sender, alias, args, index + 1);
        }
    }
}
